package form.dispatchers {
	import form.events.FormElementEvent;
	import form.interfaces.IFormElement;
	
	import flash.display.DisplayObject;
	import flash.events.EventDispatcher;
	
	public class FormElementDispatcher extends EventDispatcher {
		private static var _instance:FormElementDispatcher;
		
		public static function get instance():FormElementDispatcher {
			if (FormElementDispatcher._instance == null) {
				FormElementDispatcher._instance = new FormElementDispatcher(new SingletonEnforcer());
			}
			return FormElementDispatcher._instance;
		}
		
		protected var elements:Array = new Array();
		
		public function FormElementDispatcher(enforcer:SingletonEnforcer) {
			this.addEventListener(FormElementEvent.INITIALIZED, this.onInitialized);
		}
		
		public function collectData(ancestor:DisplayObject):Object {
			var data:Object = new Object();
			
			var length:int = this.elements.length;
			for (var i:int = 0; i < length; i++) {
				var element:IFormElement = IFormElement(elements[i]);
				
				if (FormElementDispatcher.descended(DisplayObject(element), ancestor)) {
					var name:String = element.formName;
					var value:String = element.formValue;
					
					if (name != null && value != null) {
						if (data[name] == null) {
							data[name] = value;
						} else {
							if (data[name] is Array) {
								(data[name] as Array).push(value);
							} else {
								var array:Array = new Array();
								array.push(data[name]);
								array.push(value);
								data[name] = array;
							}
						}
					}
				}
			}
			
			return data;
		}
		
		protected function onInitialized(e:FormElementEvent):void {
			var element:IFormElement = e.element;
			
			if (element == null) {
				return;
			}
			
			elements.push(element);
		}
		
		private static function descended(descendant:DisplayObject, ancestor:DisplayObject):Boolean {
			var parent:DisplayObject = descendant;
			while (parent != null) {
				if (parent == ancestor) {
					return true;
				}
				
				parent = parent.parent;	
			}
			
			return false;
		}
	}
}

class SingletonEnforcer {}